package com.xbh.management.security;

import com.xbh.management.model.ManMenu;
import com.xbh.management.model.ManRole;
import com.xbh.management.service.MenuService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

import java.util.Collection;
import java.util.List;

/**
 * @program: management-center
 * @description: FilterInvocationSecurityMetadataSource（权限资源过滤器接口）继承了 SecurityMetadataSource（权限资源接口）
 * @author: 许宝华
 * @create: 2021-12-06 12:12
 *
 * 自定义权限资源过滤器，实现动态的权限验证
 * 它的主要责任就是当访问一个url时，返回这个url所需要的访问权限
 */
@Component
public class UserFileterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {

    private static Logger log = LoggerFactory.getLogger(UserFileterInvocationSecurityMetadataSource.class);

    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Autowired
    private MenuService menuService;


    /**
     * 返回本次访问需要的权限列表
     * @param object
     * @return
     * @throws IllegalArgumentException
     */
    @Override
    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
        log.info("进入了安全数据源");
        String requestUrl = ((FilterInvocation) object).getRequestUrl();
        //去数据库查询资源
        List<ManMenu> allMenu = menuService.queryAllMenu();
        for (ManMenu menu : allMenu) {

            if (antPathMatcher.match(menu.getOpenAddress(), requestUrl)) {
                List<ManRole> manRoles = menuService.queryAllMenuRelationRole(menu.getMenuId());
//                List<Role> roles = menu.getRoles();
                int size = manRoles.size();
                String[] values = new String[size];
                for (int i = 0; i < size; i++) {
                    values[i] = manRoles.get(i).getRoleName();
                }
                log.info("当前访问路径是{},这个url所需要的访问权限是{}", requestUrl,values);
                return SecurityConfig.createList(values);
            }
        }
        /**
         * @Author: Galen
         * @Description: 如果本方法返回null的话，意味着当前这个请求不需要任何角色就能访问
         * 此处做逻辑控制，如果没有匹配上的，返回一个默认具体权限，防止漏缺资源配置
         **/
        log.info("当前访问路径是{},这个url所需要的访问权限是{}", requestUrl, "ROLE_LOGIN");
        return SecurityConfig.createList("ROLE_LOGIN");

    }

    /**
     * 此处方法如果做了实现，返回了定义的权限资源列表，
     * Spring Security会在启动时校验每个ConfigAttribute是否配置正确，
     * 如果不需要校验，这里实现方法，方法体直接返回null即可。
     * @return
     */
    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    /**
     * 方法返回类对象是否支持校验，
     * web项目一般使用FilterInvocation来判断，或者直接返回true
     * @param clazz
     * @return
     */
    @Override
    public boolean supports(Class<?> clazz) {
        return FilterInvocation.class.isAssignableFrom(clazz);
    }
}
